/******************************************************************************

  Copyright (C), 1999-2017, Tenda Tech Co., Ltd.

 ******************************************************************************
  File Name     : database.h
  Version       : 1.0
  Author        : zengfanfan
  Created       : 2017/6/3
  Description   : declaration of attributes and operations of sqlite3 database
  History       :

******************************************************************************/
#ifndef PROD_COMMON_DBAPI_DATABASE_H
#define PROD_COMMON_DBAPI_DATABASE_H

#include <sqlite3.h>
#ifdef MYSQL
#include <mariadb/mysql.h>
#else
typedef int MYSQL, MYSQL_RES, MYSQL_ROW;
#endif
#include "result.h"

#define DB_NAME_LEN 64

#define MEM_DB_NAME     ":memory:"
#define DEF_DB_NAME     "default"

#define DEF_DB_USER     "root"
#define DEF_DB_PWD      ""
#define DEF_MYSQL_HOST  "localhost"
#define DEF_MYSQL_PORT  3306

#define DB_MAX_CMD_LEN (DB_MAX_STR_LEN * 4)
#define DB_EXEC_TIMEOUT 20// how many SECONDS shall we wait if database is locked
#define DB_WARNING_TIMEOUT 5 //seconds

typedef enum {
    DBT_SQLITE3,
    DBT_MYSQL,
    DBT_NUM
} dbtype_t;

typedef struct {
    dbtype_t type;
    char *url;
    char *database;
    char *username;
    char *password;
    char *host;
    unsigned short port;
} dblink_t;

typedef struct database {
    char *url;
    char *name;// 数据库名
    dbtype_t type;
    union {
        sqlite3 *s3db;
        MYSQL mysql;
    };
    char inited:1; // 是(1)否(0)已初始化
    char in_memory:1;
    char need_rollback;// 是(1)否(0)需要回滚
    int lock_cnt; // 是(>0)否(0)已加锁

    /*
     *  execute - 执行指定SQL语句
     *  @self: 数据库
     *  @cmd: 要执行的语句
     *  @result: 保存执行结果, 若NULL则不保存结果
     *
     *  result使用完后注意释放内存: result.free(&result)
     *
     *  return: 1-ok, 0-fail
     */
    int (*execute)(struct database *self, char *cmd, db_result_t *result);

    /*
     *  lock - 加锁
     *  @self: 数据库
     *
     *  申请互斥锁, 若锁已被占用, 则挂起等待, 直到占有者主动释放锁
     *  处理完后注意要释放锁( self->unlock )
     *
     *  这个lock函数是保证多条语句执行过程中不会被其他人修改,
     *  即: 执行单条数据库语句是不需要lock的
     */
    void (*lock)(struct database *self);

    /*
     *  unlock - 解锁
     *  @self: 数据库
     *
     *  释放互斥锁
     *  与 self->lock 配合使用
     */
    void (*unlock)(struct database *self);

    /*
     *  rollback - 回滚事务
     *  @self: 数据库
     *
     *  在事务中 (lock 和 unlock 之间) 调用, 回滚整个事务
     */
    void (*rollback)(struct database *self);

    /*
     *  close - 关闭数据库连接
     *  @self: 数据库
     */
    void (*close)(struct database *self);
} database_t;

/*
 *  init_database - 初始化数据库
 *  @self: 数据库
 *  @url: 数据库URL (sqlite3://<database>; mysql://[<username>[:<password>]@]<host>[:<port>]/database)
 *
 *  仅在 db_table_init 内使用, 外部不应该调用该函数
 *
 *  returns: 1-ok, 0-fail
 */
int init_database(database_t *self, char *url);
int db_table_exists(database_t *self, char *tb_name);

#endif // PROD_COMMON_DBAPI_DATABASE_H
